iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
Security

picoCTF系列 第 20

[Day 20] Safe Opener 2 & Reverse

  • 分享至 

  • xImage
  •  

今天選擇的題目因為都沒有太困難,所以會一次寫兩題。

第一題,看到題目,知道要找到遺失的鑰匙,並且提示告訴我們,會用到 decompiler。
https://ithelp.ithome.com.tw/upload/images/20240825/20168342fdbt1oIF0O.png
hint:Download and try to decompile the file.

依照題目,下載給予的檔案,得到一個 java compile 過後的 class 檔。

$ ls -l
total 12
-rw-r--r-- 1 root            root            4443 Aug  2 06:00 README.txt
-rw-rw-r-- 1 user            user            2036 Mar 16  2023 SafeOpener.class

fileexiftool 查看詳細資料,沒有發現什麼特別的。

$ file SafeOpener.class 
SafeOpener.class: compiled Java class data, version 52.0 (Java 1.8)
$ exiftool SafeOpener.class 
ExifTool Version Number         : 12.40
File Name                       : SafeOpener.class
Directory                       : .
File Size                       : 2036 bytes
File Modification Date/Time     : 2023:03:16 03:15:29+00:00
File Access Date/Time           : 2024:08:02 06:01:58+00:00
File Inode Change Date/Time     : 2024:08:02 06:01:05+00:00
File Permissions                : -rw-rw-r--
File Type                       : Mach-O fat binary executable
File Type Extension             : 
MIME Type                       : application/octet-stream
CPU Count                       : 52

執行檔案後,會發現有三次輸入密碼的機會,隨便輸入,得到一些亂碼。

$ java SafeOpener 
Enter password for the safe: 123
MTIz
Password is incorrect

You have  2 attempt(s) left
Enter password for the safe: 111
MTEx
Password is incorrect

You have  1 attempt(s) left
Enter password for the safe: 222
MjIy
Password is incorrect

You have  0 attempt(s) left

根據提示,於是乎直接用 Decompiler,把 class 檔還原成原始的 java 檔。可以發現 flag 就在 opensafe 的函式裡。在這裡我選擇使用線上的 java decompiler ( .JAR and .Class to Java decompiler )。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Base64;
import java.util.Base64.Encoder;

public class SafeOpener {
   public static void main(String[] args) throws IOException {
      BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
      Encoder encoder = Base64.getEncoder();
      String encodedkey = "";
      String key = "";

      for(int i = 0; i < 3; ++i) {
         System.out.print("Enter password for the safe: ");
         key = keyboard.readLine();
         encodedkey = encoder.encodeToString(key.getBytes());
         System.out.println(encodedkey);
         boolean isOpen = openSafe(encodedkey);
         if (isOpen) {
            break;
         }

         System.out.println("You have  " + (2 - i) + " attempt(s) left");
      }

   }

   public static boolean openSafe(String password) {
      String encodedkey = "picoCTF{SAf3_0p3n3rr_y0u_solv3d_it_5bfbd6f1}";
      if (password.equals(encodedkey)) {
         System.out.println("Sesame open");
         return true;
      } else {
         System.out.println("Password is incorrect\n");
         return false;
      }
   }
}
    

繼續下一題,題目需求要找 password,並且沒有提示。
https://ithelp.ithome.com.tw/upload/images/20240825/20168342oFpMOruKv2.png

老樣子,先用 ls 看下載了甚麼,發現得到一個未知檔案 ret。

$ ls -l
total 28
-rw-r--r-- 1 root            root             4443 Aug  2 06:00 README.txt
-rw-rw-r-- 1 user            user             16888 Mar 16  2023 ret

接著用 file 查看詳細資料,發現是執行檔。

$ file ret 
ret: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=64856d07d138e412faf30b9722d92f507e3b5c9c, for GNU/Linux 3.2.0, not stripped

於是試著執行題目給予的檔案,程式會要求輸入密碼來解鎖,我們先隨便填入。

$ ./ret
-bash: ./ret: Permission denied
$ chmod +x ret 
$ ./ret 
Enter the password to unlock this file: 123
You entered: 123
Access denied

因為 ret 是 elf file ,所以使用 readelf ,檢視 ret 檔案詳情。
先用查看 header 裡有沒有甚麼資訊,結果沒有甚麼發現。

$ readelf -h ret 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x10e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14904 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

於是我查看 Symbol ,並且可以從 symbol table 知道執行了什麼。
並且可以看到第 36 行看到執行了 ret.c 的檔案,第 56 行也可以看到有執行 strcmp 的函式,於是可知 ret 檔案裡應該含有 password。

$ readelf -s ret 

Symbol table '.dynsym' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __[...]@GLIBC_2.4 (3)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     7: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __[...]@GLIBC_2.7 (4)
     9: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
    10: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5 (2)

Symbol table '.symtab' contains 69 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000318     0 SECTION LOCAL  DEFAULT    1 .interp
     2: 0000000000000338     0 SECTION LOCAL  DEFAULT    2 .note.gnu.property
     3: 0000000000000358     0 SECTION LOCAL  DEFAULT    3 .note.gnu.build-id
     4: 000000000000037c     0 SECTION LOCAL  DEFAULT    4 .note.ABI-tag
     5: 00000000000003a0     0 SECTION LOCAL  DEFAULT    5 .gnu.hash
     6: 00000000000003c8     0 SECTION LOCAL  DEFAULT    6 .dynsym
     7: 00000000000004d0     0 SECTION LOCAL  DEFAULT    7 .dynstr
     8: 0000000000000594     0 SECTION LOCAL  DEFAULT    8 .gnu.version
     9: 00000000000005b0     0 SECTION LOCAL  DEFAULT    9 .gnu.version_r
    10: 00000000000005f0     0 SECTION LOCAL  DEFAULT   10 .rela.dyn
    11: 00000000000006b0     0 SECTION LOCAL  DEFAULT   11 .rela.plt
    12: 0000000000001000     0 SECTION LOCAL  DEFAULT   12 .init
    13: 0000000000001020     0 SECTION LOCAL  DEFAULT   13 .plt
    14: 0000000000001080     0 SECTION LOCAL  DEFAULT   14 .plt.got
    15: 0000000000001090     0 SECTION LOCAL  DEFAULT   15 .plt.sec
    16: 00000000000010e0     0 SECTION LOCAL  DEFAULT   16 .text
    17: 0000000000001348     0 SECTION LOCAL  DEFAULT   17 .fini
    18: 0000000000002000     0 SECTION LOCAL  DEFAULT   18 .rodata
    19: 00000000000020a4     0 SECTION LOCAL  DEFAULT   19 .eh_frame_hdr
    20: 00000000000020e8     0 SECTION LOCAL  DEFAULT   20 .eh_frame
    21: 0000000000003d98     0 SECTION LOCAL  DEFAULT   21 .init_array
    22: 0000000000003da0     0 SECTION LOCAL  DEFAULT   22 .fini_array
    23: 0000000000003da8     0 SECTION LOCAL  DEFAULT   23 .dynamic
    24: 0000000000003f98     0 SECTION LOCAL  DEFAULT   24 .got
    25: 0000000000004000     0 SECTION LOCAL  DEFAULT   25 .data
    26: 0000000000004010     0 SECTION LOCAL  DEFAULT   26 .bss
    27: 0000000000000000     0 SECTION LOCAL  DEFAULT   27 .comment
    28: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    29: 0000000000001110     0 FUNC    LOCAL  DEFAULT   16 deregister_tm_clones
    30: 0000000000001140     0 FUNC    LOCAL  DEFAULT   16 register_tm_clones
    31: 0000000000001180     0 FUNC    LOCAL  DEFAULT   16 __do_global_dtors_aux
    32: 0000000000004010     1 OBJECT  LOCAL  DEFAULT   26 completed.8061
    33: 0000000000003da0     0 OBJECT  LOCAL  DEFAULT   22 __do_global_dtor[...]
    34: 00000000000011c0     0 FUNC    LOCAL  DEFAULT   16 frame_dummy
    35: 0000000000003d98     0 OBJECT  LOCAL  DEFAULT   21 __frame_dummy_in[...]
    36: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ret.c
    37: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    38: 00000000000021ec     0 OBJECT  LOCAL  DEFAULT   20 __FRAME_END__
    39: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    40: 0000000000003da0     0 NOTYPE  LOCAL  DEFAULT   21 __init_array_end
    41: 0000000000003da8     0 OBJECT  LOCAL  DEFAULT   23 _DYNAMIC
    42: 0000000000003d98     0 NOTYPE  LOCAL  DEFAULT   21 __init_array_start
    43: 00000000000020a4     0 NOTYPE  LOCAL  DEFAULT   19 __GNU_EH_FRAME_HDR
    44: 0000000000003f98     0 OBJECT  LOCAL  DEFAULT   24 _GLOBAL_OFFSET_TABLE_
    45: 0000000000001000     0 FUNC    LOCAL  DEFAULT   12 _init
    46: 0000000000001340     5 FUNC    GLOBAL DEFAULT   16 __libc_csu_fini
    47: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterT[...]
    48: 0000000000004000     0 NOTYPE  WEAK   DEFAULT   25 data_start
    49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5
    50: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   25 _edata
    51: 0000000000001348     0 FUNC    GLOBAL HIDDEN    17 _fini
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail[...]
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
    54: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_mai[...]
    55: 0000000000004000     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
    56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@@GLIBC_2.2.5
    57: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    58: 0000000000004008     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
    59: 0000000000002000     4 OBJECT  GLOBAL DEFAULT   18 _IO_stdin_used
    60: 00000000000012d0   101 FUNC    GLOBAL DEFAULT   16 __libc_csu_init
    61: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   26 _end
    62: 00000000000010e0    47 FUNC    GLOBAL DEFAULT   16 _start
    63: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
    64: 00000000000011c9   250 FUNC    GLOBAL DEFAULT   16 main
    65: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __isoc99_scanf@@[...]
    66: 0000000000004010     0 OBJECT  GLOBAL HIDDEN    25 __TMC_END__
    67: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMC[...]
    68: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@[...]

接著用 strings 把 ret 裡可列印的文字列出,找到 flag。

$ strings ret | grep 'pico'
picoCTF{H
Password correct, please see flag: picoCTF{3lf_r3v3r5ing_succe55ful_d7b14d43}

小結:
練習 java decompiler,並且知道從 elf 檔案中的 symbol table 推敲出有關檔案的線索。


上一篇
[Day 19] Secret of the Polyglot & tunn3l v1s10n
下一篇
[Day 21] SOAP
系列文
picoCTF30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言